package cn.zwx.member.svc.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.zwx.base.exception.BizWrapException;
import cn.zwx.common.mybatis.query.LambdaQueryWrapperX;
import cn.zwx.member.svc.domain.constans.MemberConstant;
import cn.zwx.member.svc.domain.convert.address.AddressConvert;
import cn.zwx.member.svc.domain.convert.exception.ExceptionWrap;
import cn.zwx.member.svc.domain.entity.MemberAddressEntity;
import cn.zwx.member.svc.domain.entity.MemberDistrictsEntity;
import cn.zwx.member.svc.domain.enums.MemberBizCodeEnum;
import cn.zwx.member.svc.dto.AddressCreateReqDTO;
import cn.zwx.member.svc.dto.AddressQueryDTO;
import cn.zwx.member.svc.dto.AddressUpdateReqDTO;
import cn.zwx.member.svc.mapper.MemberAddressMapper;
import cn.zwx.member.svc.service.AddressService;
import cn.zwx.member.svc.service.DistrictsService;
import cn.zwx.member.svc.vo.AddressRespVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhangwenxue
 */
@Service
public class AddressServiceImpl  implements AddressService {

    @Resource
    private MemberAddressMapper addressMapper;

    @Resource
    private DistrictsService districtsService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createAddress(AddressCreateReqDTO dto) throws BizWrapException {
        // 1.如果添加的是默认收件地址，则将原默认地址修改为非默认
        Boolean defaultStatus = dto.getDefaultStatus();
        if (Boolean.TRUE.equals(defaultStatus)){
            this.handleDefaultAddress(dto.getUserId(),null);
        }
        // 2.构建对象
        MemberAddressEntity entity = this.handleAddressEntity(dto);
        addressMapper.insert(entity);
        // 3.返回参数
        return entity.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateAddress(AddressUpdateReqDTO dto) throws BizWrapException {
        // 1.校验存在,校验是否能够操作
        this.validAddressExists(dto.getUserId(), dto.getId());
        // 2.处理默认地址
        if (Boolean.TRUE.equals(dto.getDefaultStatus())){
            this.handleDefaultAddress(dto.getUserId(),dto.getId());
        }
        // 3.更新
        AddressCreateReqDTO createReqDTO = new AddressCreateReqDTO();
        MemberAddressEntity entity = this.handleAddressEntity(createReqDTO);
        entity.setId(dto.getId());
        entity.setCreateTime(null);
        entity.setUpdateTime(new Date());
        // 4.返回参数
        int updateById = addressMapper.updateById(entity);
        return updateById == 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteAddress(Long id,Long userId) throws BizWrapException {
        // 校验存在,校验是否能够操作
        validAddressExists(userId, id);
        // 删除
        int deleteById = addressMapper.deleteById(id);
        // 返回
        return deleteById == 1;
    }

    @Override
    public AddressRespVO getAddress(AddressQueryDTO dto) {
        MemberAddressEntity address = addressMapper.selectOne(new LambdaQueryWrapperX<MemberAddressEntity>()
                .eq(MemberAddressEntity::getId, dto.getId())
                .eq(MemberAddressEntity::getUserId, dto.getUserId()));
        if (Objects.isNull(address)){
            return null;
        }
        return getAddressRespVO(address);

    }

    @Override
    public AddressRespVO getDefaultUserAddress(Long userId) {
        // 查询默认地址
        List<MemberAddressEntity> defaultAddressList = this.getDefaultAddress(userId);
        // 返回参数
        return getAddressRespVO(CollUtil.getFirst(defaultAddressList));
    }

    @Override
    public List<AddressRespVO> getAddressList(Long userId) {
        // 查询用户地址信息
        LambdaQueryWrapperX<MemberAddressEntity> wrapperX = new LambdaQueryWrapperX<>();
        wrapperX.eq(MemberAddressEntity::getUserId, userId);
        List<MemberAddressEntity> selectedList = addressMapper.selectList(wrapperX);
        // 返回参数处理
        if (CollUtil.isEmpty(selectedList)){
            return new ArrayList<>();
        }
        List<AddressRespVO> returnList = new ArrayList<>(selectedList.size());
        for (MemberAddressEntity entity : selectedList) {
            returnList.add(getAddressRespVO(entity));
        }
        return returnList;
    }


    private static AddressRespVO getAddressRespVO(MemberAddressEntity address) {
        AddressRespVO convert = AddressConvert.convert(address);
        convert.setDetailAddress(address.getAddress());
        convert.setName(address.getContact());
        convert.setDefaultStatus(address.getIsDefault());
        convert.setCreateTime(address.getCreateTime());
        convert.setProvinceName(address.getProvinceName());
        convert.setCityName(address.getCityName());
        convert.setDistrictName(address.getDistrictName());
        convert.setMobile(address.getPhone());
        convert.setUserId(Long.valueOf(address.getUserId()));
        return convert;
    }

    private void validAddressExists(Long userId, Long id) throws BizWrapException {
        AddressQueryDTO queryDTO = new AddressQueryDTO();
        queryDTO.setId(id);
        queryDTO.setUserId(userId);
        AddressRespVO address = this.getAddress(queryDTO);
        if (Objects.isNull(address)){
            throw ExceptionWrap.wrap(MemberBizCodeEnum.ADDRESS_NOT_EXISTS);
        }
    }


    private MemberAddressEntity handleAddressEntity(AddressCreateReqDTO dto) throws BizWrapException {
        MemberAddressEntity entity = AddressConvert.convert(dto);
        List<Integer> districtIdList = new ArrayList<>();
        districtIdList.add(Integer.valueOf(entity.getDistrictId()));
        districtIdList.add(Integer.valueOf(entity.getProvinceId()));
        districtIdList.add(Integer.valueOf(entity.getCityId()));
        List<MemberDistrictsEntity> districtList = districtsService.selectDistrictIdList(districtIdList);
        if (CollUtil.isEmpty(districtList) || districtList.size() != MemberConstant.INT_3){
            throw ExceptionWrap.wrap(MemberBizCodeEnum.ADDRESS_VALIDATE_ERROR);
        }
        Map<Integer, MemberDistrictsEntity> districtMap = districtList.stream()
                .collect(Collectors.toMap(MemberDistrictsEntity::getDistrictId, district -> district));
        entity.setDistrictName(districtMap.get(Integer.valueOf(entity.getDistrictId())).getName());
        entity.setProvinceName(districtMap.get(Integer.valueOf(entity.getProvinceId())).getName());
        entity.setCityName(districtMap.get(Integer.valueOf(entity.getCityId())).getName());
        entity.setContact(dto.getName());
        entity.setIsDefault(dto.getDefaultStatus());
        entity.setAddress(dto.getDetailAddress());
        entity.setUpdateTime(new Date());
        entity.setCreateTime(new Date());
        return entity;
    }

    private void handleDefaultAddress(Long userId, Long addressId) {
        // 查询默认地址
        List<MemberAddressEntity> defaultAddressList = this.getDefaultAddress(userId);
        if (CollUtil.isEmpty(defaultAddressList)){
            return;
        }
        if (Objects.nonNull(addressId)){
            // 排除自己
            defaultAddressList = defaultAddressList.stream()
                    .filter(t->!t.getId().equals(addressId)).collect(Collectors.toList());
        }
        if (CollUtil.isEmpty(defaultAddressList)){
            return;
        }
        List<MemberAddressEntity>  updateList = new ArrayList<>(defaultAddressList.size());
        for (MemberAddressEntity addressEntity : defaultAddressList) {
            MemberAddressEntity entity = new MemberAddressEntity();
            entity.setUpdateTime(new Date());
            entity.setId(addressEntity.getId());
            entity.setIsDefault(Boolean.FALSE);
            updateList.add(entity);
        }
        addressMapper.updateBatch(updateList);
    }

    private List<MemberAddressEntity> getDefaultAddress(Long userId) {
        LambdaQueryWrapperX<MemberAddressEntity> wrapperX = new LambdaQueryWrapperX<>();
        wrapperX.eq(MemberAddressEntity::getUserId, userId);
        wrapperX.eqIfPresent(MemberAddressEntity::getIsDefault,true);
        return addressMapper.selectList(wrapperX);
    }


}
